// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraSettingValueDiscreteDynamic_AudioOutputDevice.h"

#include "AudioDeviceNotificationSubsystem.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraSettingValueDiscreteDynamic_AudioOutputDevice)

#define LOCTEXT_NAMESPACE "LyraSettings"

/**
 * 初始化时调用
 */
void ULyraSettingValueDiscreteDynamic_AudioOutputDevice::OnInitialized()
{
	Super::OnInitialized(); // 调用父类初始化方法

	DevicesObtainedCallback.BindUFunction(this, FName("OnAudioOutputDevicesObtained")); // 绑定设备获取完成回调
	DevicesSwappedCallback.BindUFunction(this, FName("OnCompletedDeviceSwap")); // 绑定设备交换完成回调

	if (UAudioDeviceNotificationSubsystem* AudioDeviceNotifSubsystem = UAudioDeviceNotificationSubsystem::Get()) // 获取音频设备通知子系统
	{
		AudioDeviceNotifSubsystem->DeviceAddedNative.AddUObject(this, &ULyraSettingValueDiscreteDynamic_AudioOutputDevice::DeviceAddedOrRemoved); // 添加设备添加事件
		AudioDeviceNotifSubsystem->DeviceRemovedNative.AddUObject(this, &ULyraSettingValueDiscreteDynamic_AudioOutputDevice::DeviceAddedOrRemoved); // 添加设备移除事件
		//AudioDeviceNotifSubsystem->DeviceSwitchedNative.AddUObject(this, &ULyraSettingValueDiscreteDynamic_AudioOutputDevice::DeviceSwitched); // 注释掉的设备切换事件
		AudioDeviceNotifSubsystem->DefaultRenderDeviceChangedNative.AddUObject(this, &ULyraSettingValueDiscreteDynamic_AudioOutputDevice::DefaultDeviceChanged); // 添加默认渲染设备更改事件
	}

	UAudioMixerBlueprintLibrary::GetAvailableAudioOutputDevices(this, DevicesObtainedCallback); // 获取可用的音频输出设备
}

/**
 * 音频输出设备获取完成时调用
 */
void ULyraSettingValueDiscreteDynamic_AudioOutputDevice::OnAudioOutputDevicesObtained(const TArray<FAudioOutputDeviceInfo>& AvailableDevices)
{
	int32 NewSize = AvailableDevices.Num(); // 新大小
	OutputDevices.Reset(NewSize++); // 重置输出设备数组
	OutputDevices.Append(AvailableDevices); // 附加可用设备

	OptionValues.Reset(NewSize); // 重置选项值
	OptionDisplayTexts.Reset(NewSize); // 重置选项显示文本

	// 占位符 - 需要是第一个选项，以便稍后格式化默认设备字符串
	AddDynamicOption(TEXT(""), FText::GetEmpty()); // 添加动态选项
	FString SystemDefaultDeviceName; // 系统默认设备名称

	for (const FAudioOutputDeviceInfo& DeviceInfo : OutputDevices) // 遍历输出设备
	{
		if (!DeviceInfo.DeviceId.IsEmpty() && !DeviceInfo.Name.IsEmpty()) // 如果设备ID和名称不为空
		{
			// 系统默认
			if (DeviceInfo.bIsSystemDefault) // 如果是系统默认设备
			{
				SystemDefaultDeviceId = DeviceInfo.DeviceId; // 设置系统默认设备ID
				SystemDefaultDeviceName = DeviceInfo.Name; // 设置系统默认设备名称
			}

			// 当前设备
			if (DeviceInfo.bIsCurrentDevice) // 如果是当前设备
			{
				CurrentDeviceId = DeviceInfo.DeviceId; // 设置当前设备ID
			}

			// 添加菜单选项
			AddDynamicOption(DeviceInfo.DeviceId, FText::FromString(DeviceInfo.Name)); // 添加动态选项
		}
	}

	OptionDisplayTexts[0] = FText::Format(LOCTEXT("DefaultAudioOutputDevice", "默认输出 - {0}"), FText::FromString(SystemDefaultDeviceName)); // 设置默认音频输出设备文本
	SetDefaultValueFromString(TEXT("")); // 从字符串设置默认值
	RefreshEditableState(); // 刷新可编辑状态

	//LastKnownGoodIndex = GetDiscreteOptionDefaultIndex(); // 注释掉的最后已知良好索引
	//SetDiscreteOptionByIndex(GetDiscreteOptionIndex()); // 注释掉的根据索引设置离散选项
}

/**
 * 设备交换完成时调用
 */
void ULyraSettingValueDiscreteDynamic_AudioOutputDevice::OnCompletedDeviceSwap(const FSwapAudioOutputResult& SwapResult)
{
	//if (SwapResult.Result == ESwapAudioOutputDeviceResultState::Failure) // 如果交换结果失败
	//{
	//	UE_LOG(LogLyra, VeryVerbose, TEXT("AudioOutputDevice failure! Resetting to: %s"), *(OptionDisplayTexts[LastKnownGoodIndex].ToString())); // 记录音频输出设备失败日志
	//	if (OptionValues.Num() < LastKnownGoodIndex && SwapResult.RequestedDeviceId != OptionValues[LastKnownGoodIndex]) // 如果选项值数量小于最后已知良好索引且请求设备ID不等于选项值
	//	{
	//		SetDiscreteOptionByIndex(LastKnownGoodIndex); // 根据最后已知良好索引设置离散选项
	//	}
	//
	//	// 移除无效设备
	//	if (SwapResult.RequestedDeviceId != SystemDefaultDeviceId) // 如果请求设备ID不等于系统默认设备ID
	//	{
	//		OutputDevices.RemoveAll([&SwapResult](FAudioOutputDeviceInfo& Device) // 移除所有匹配设备
	//		{
	//			return Device.DeviceId == SwapResult.RequestedDeviceId; // 匹配设备ID
	//		});
	//
	//		RemoveDynamicOption(SwapResult.RequestedDeviceId); // 移除动态选项
	//		RefreshEditableState(); // 刷新可编辑状态
	//	}
	//}
}

/**
 * 设备添加或移除时调用
 */
void ULyraSettingValueDiscreteDynamic_AudioOutputDevice::DeviceAddedOrRemoved(FString DeviceId)
{
	UAudioMixerBlueprintLibrary::GetAvailableAudioOutputDevices(this, DevicesObtainedCallback); // 获取可用的音频输出设备
}

/**
 * 默认设备更改时调用
 */
void ULyraSettingValueDiscreteDynamic_AudioOutputDevice::DefaultDeviceChanged(EAudioDeviceChangedRole InRole, FString DeviceId)
{
	UAudioMixerBlueprintLibrary::GetAvailableAudioOutputDevices(this, DevicesObtainedCallback); // 获取可用的音频输出设备
}

/**
 * 根据索引设置离散选项
 */
void ULyraSettingValueDiscreteDynamic_AudioOutputDevice::SetDiscreteOptionByIndex(int32 Index)
{
	Super::SetDiscreteOptionByIndex(Index); // 调用父类设置离散选项方法
	//UE_LOG(LogLyra, VeryVerbose, TEXT("AudioOutputDevice set to %s - %s"), *(OptionDisplayTexts[Index].ToString()), *OptionValues[Index]); // 记录音频输出设备设置日志
	//bRequestDefault = false; // 注释掉的请求默认
	//
	//FString RequestedAudioDeviceId = GetValueAsString(); // 获取请求音频设备ID
	//
	//// 如果用户选择了默认，获取正确的设备ID
	//const int32 DefaultOptionIndex = GetDiscreteOptionDefaultIndex(); // 获取默认选项索引
	//if (Index == DefaultOptionIndex) // 如果索引等于默认选项索引
	//{
	//	RequestedAudioDeviceId = SystemDefaultDeviceId; // 设置请求音频设备ID为系统默认设备ID
	//}
	//
	//// 仅当请求的设备ID与当前不同时交换
	//if (RequestedAudioDeviceId == CurrentDeviceId) // 如果请求音频设备ID等于当前设备ID
	//{
	//	LastKnownGoodIndex = Index; // 设置最后已知良好索引
	//	UE_LOG(LogLyra, VeryVerbose, TEXT("AudioOutputDevice (Not Swapping) - LKG set to index :%d"), LastKnownGoodIndex); // 记录音频输出设备不交换日志
	//}
	//else
	//{
	//	bRequestDefault = (Index == DefaultOptionIndex); // 设置请求默认
	//	UAudioMixerBlueprintLibrary::SwapAudioOutputDevice(LocalPlayer, RequestedAudioDeviceId, DevicesSwappedCallback); // 交换音频输出设备
	//	UE_LOG(LogLyra, VeryVerbose, TEXT("AudioOutputDevice requesting %s"), *RequestedAudioDeviceId); // 记录音频输出设备请求日志
	//}
}

#undef LOCTEXT_NAMESPACE